Skip to content

PACKUSWB:无符号饱和打包

PACKUSWB(Pack with Unsigned Saturation)把两个操作数中的有符号 word(int16)转换成无符号 byte(uint8),再打包进目标寄存器。转换采用饱和规则,不会简单截断高位。

操作码
66 0F 67 /r
指令集
SSE2
英文全称
Pack with Unsigned Saturation
参考资料
INTEL SDM
页码
919
01PACKUSWB02xmm003xmm1/m128
01
无符号饱和打包PACKUSWBmnemonic

把两组有符号 16 位整数压缩成无符号 8 位整数,并将越界值钳制到 0…255。

02
目标与第一源操作数xmm0destination

原有的 8 个 int16 转换后进入结果的低 8 个 byte,随后被结果覆盖。

03
第二源操作数xmm1/m128source

另外 8 个 int16 转换后进入结果的高 8 个 byte。

饱和规则

对每个有符号 16 位输入 x,输出为:

text
          0,  x < 0
sat_u8 =  x,  0 <= x <= 255
        255,  x > 255
输入 int16输出 uint8原因
-200低于无符号 byte 下界
00范围内
127127范围内
255255范围内
256255高于无符号 byte 上界
1000255高于无符号 byte 上界

这与普通窄化转换不同。例如,截断 256 的低 8 位会得到 0,而 PACKUSWB 得到 255

两个寄存器如何打包

每个 XMM 源包含 8 个 word,结果 XMM 包含 16 个 byte。以下数组都按低位元素到高位元素书写:

PACKUSWB · SIGNED WORD → UNSIGNED BYTE
xmm0 · int16
xmm0[127:0]
xmm0[0]-20INT16
xmm0[1]0INT16
xmm0[2]1INT16
xmm0[3]127INT16
xmm0[4]255INT16
xmm0[5]256INT16
xmm0[6]1000INT16
xmm0[7]42INT16
xmm1 · int16
xmm1[127:0]
xmm1[0]300INT16
xmm1[1]254INT16
xmm1[2]-1INT16
xmm1[3]128INT16
xmm1[4]10INT16
xmm1[5]500INT16
xmm1[6]255INT16
xmm1[7]256INT16
xmm0 · uint8
xmm0[127:0]
xmm0[0]0UINT8
xmm0[1]0UINT8
xmm0[2]1UINT8
xmm0[3]127UINT8
xmm0[4]255UINT8
xmm0[5]255UINT8
xmm0[6]255UINT8
xmm0[7]42UINT8
xmm0[8]255UINT8
xmm0[9]254UINT8
xmm0[10]0UINT8
xmm0[11]128UINT8
xmm0[12]10UINT8
xmm0[13]255UINT8
xmm0[14]255UINT8
xmm0[15]255UINT8

输入元素各占 16 bits,饱和后各占 8 bits;每个圆球表示一个完整元素。结果低 8 bytes 来自 xmm0,高 8 bytes 来自 xmm1。

PACKUSWB · REGISTER OPERATIONX86 · CONVERT
元素数量向量宽度 ÷ 元素宽度16
vs2 · xmm1第一来源
xmm1[127:0]
vs2[15]168 bits
vs2[14]158 bits
vs2[13]148 bits
vs2[12]138 bits
vs2[11]128 bits
vs2[10]118 bits
vs2[9]108 bits
vs2[8]98 bits
vs2[7]88 bits
vs2[6]78 bits
vs2[5]68 bits
vs2[4]58 bits
vs2[3]48 bits
vs2[2]38 bits
vs2[1]28 bits
vs2[0]18 bits
vs1 · xmm2第二来源
xmm2[127:0]
vs1[15]328 bits
vs1[14]318 bits
vs1[13]308 bits
vs1[12]298 bits
vs1[11]288 bits
vs1[10]278 bits
vs1[9]268 bits
vs1[8]258 bits
vs1[7]248 bits
vs1[6]238 bits
vs1[5]228 bits
vs1[4]218 bits
vs1[3]208 bits
vs1[2]198 bits
vs1[1]188 bits
vs1[0]178 bits
vd · xmm0(结果)convert
xmm0[127:0]
vd[15]16convert
vd[14]15convert
vd[13]14convert
vd[12]13convert
vd[11]12convert
vd[10]11convert
vd[9]10convert
vd[8]9convert
vd[7]8convert
vd[6]7convert
vd[5]6convert
vd[4]5convert
vd[3]4convert
vd[2]3convert
vd[1]2convert
vd[0]1convert
每个圆球代表一个完整元素强调背景:目标写入高索引在左、低索引在右
text
xmm0 words = [-20,   0,  1, 127, 255, 256, 1000, 42]
xmm1 words = [300, 254, -1, 128,  10, 500,  255, 256]

pack xmm0  = [  0,   0,  1, 127, 255, 255, 255, 42]
pack xmm1  = [255, 254,  0, 128,  10, 255, 255, 255]

result     = [  0,   0,  1, 127, 255, 255, 255, 42, 255, 254,  0, 128,  10, 255, 255, 255]

也就是说,第一源的转换结果进入目标低半部,第二源的转换结果进入目标高半部:

text
DEST.byte[0..7]  = sat_u8(OLD_DEST.word[0..7])
DEST.byte[8..15] = sat_u8(SRC.word[0..7])

其他编码形式

指令输入与输出指令集特点
PACKUSWB mm, mm/m648 × int16 → 8 × uint8MMX使用 MMX 寄存器
PACKUSWB xmm1, xmm2/m12816 × int16 → 16 × uint8SSE2两操作数,覆盖目标
VPACKUSWB xmm1, xmm2, xmm3/m12816 × int16 → 16 × uint8AVX三操作数
VPACKUSWB ymm1, ymm2, ymm3/m25632 × int16 → 32 × uint8AVX2每个 128 位 lane 独立打包
VPACKUSWB zmm1 {k1}{z}, zmm2, zmm3/m51264 × int16 → 64 × uint8AVX-512BW支持 byte 粒度写掩码

PACKUSWB 不修改 EFLAGS,也不产生 SIMD 浮点异常。

SIGNAL MAINTAINED · BUILT FROM MARKDOWN